package controllers;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import com.google.gson.JsonArray;

import models.Comible;
import models.ComibleDTO;
import models.ComidaDieta;
import models.Dieta;
import models.Frecuente;
import models.Ingerido;
import models.Paciente;
import models.Plan;
import models.Plato;
import models.PorcionAlimento;
import models.TipoComida;
import play.mvc.With;
import util.Utilities;
import controllers.securesocial.SecureSocial;

@With(SecureSocial.class)
public class Dietas extends CustomCRUD {
	
	public static void index() {
		render();
	}
	
	public static void show(Long planId, Long dietaId) throws Exception {
		ObjectType type = ObjectType.get(getControllerClass());
		notFoundIfNull(type);
		
		Plan plan = Plan.findById(planId);
		
		Dieta dieta = dietaId == null ? Dieta.findByDiaActual(planId) : (Dieta) Dieta.findById(dietaId);
		String diaSemana = Utilities.getNombreDia(dieta.getFecha()).substring(0, 2).replace("á", "a");
		
		// ids de la dieta segun cada dia
		Long[] diasDieta = getIdsSemanaDieta(planId);
		
		List<Frecuente> frecuentes = buscarFrecuentes();
		render(getControllerName() + "/show2.html", type, plan, frecuentes, dieta, diaSemana, diasDieta);
	}
	
	public static List<Frecuente> buscarFrecuentes() {
		
		Paciente paciente = (Paciente)getUsuarioLogueado();
		
		return Frecuente.findByCantidad(paciente.getId());
	}
	
	/**
	 * Retorna en formato Json los "comibles" encontrado segun el nombre
	 */
	public static void buscarAlimento(String nombre) {
		//TODO: cambiar nombre método
		List<Comible> comibles = Comible.findByNombre(nombre);
		
		List<ComibleDTO> comiblesDTOs = new ArrayList<ComibleDTO>();
		
		for(Comible c: comibles){
			ComibleDTO comibleDTO = new ComibleDTO(c.getNombre());
			comibleDTO.setIconPath(c.getIconPath());
			comibleDTO.setId(c.id);
			comiblesDTOs.add(comibleDTO);
		}
			
		renderJSON(comiblesDTOs);
	}
	
	/**
	 * Retorna en formato Json los "comibles" pertenecientes a la EA buscada
	 */
	public static void buscarAlimentoEA(String nombre) {
		List<Comible> comibles = Plato.findByAutorEA(nombre);
		List<ComibleDTO> comiblesDTOs = new ArrayList<ComibleDTO>();
		
		for(Comible c: comibles){
			ComibleDTO comibleDTO = new ComibleDTO(c.getNombre());
			comibleDTO.setIconPath(c.getIconPath());
			comibleDTO.setId(c.id);
			comiblesDTOs.add(comibleDTO);
		}
		
		renderJSON(comiblesDTOs);
	}

	/**
	 * Retorna en formato Json los "comibles" encontrado segun el nombre
	 */
	public static void buscarPlatos(String platoId) {
		Plato plato = Plato.findById(Long.parseLong(platoId));
		
		List<ComibleDTO> comiblesDTOs = new ArrayList<ComibleDTO>();
		
		for(PorcionAlimento porcionAlimento: plato.getPorcionesAlimentos()){
			ComibleDTO comibleDTO = new ComibleDTO(porcionAlimento.getAlimento().getNombre());
			comibleDTO.setId(porcionAlimento.getAlimento().id);
			comibleDTO.setCaloriasPorPorcion(porcionAlimento.getAlimento().getCaloriasPorPorcion());
			comibleDTO.setIconPath(porcionAlimento.getAlimento().getIconPath());
			comibleDTO.setCantidad(porcionAlimento.getCantidad());
			comiblesDTOs.add(comibleDTO);
		}
		
		renderJSON(comiblesDTOs);
	}
	
	/**
	 * Registrar de a un ingerido segun el tipo de comida
	 */
	public static Integer registrarIngerido(Long dietaId, String comida, Long alimentoId, Integer cantPorciones) throws Exception {
		Dieta dieta = Dieta.findById(dietaId);
		Comible comible = Comible.findById(alimentoId);
		
		// cero indica que no tiene sugeridos, solo cant ingeridas
		Ingerido ingerido = new Ingerido(comible, 0);
		ingerido.setCantPorcionesIngeridas(cantPorciones);
		ingerido.setConsumido(Boolean.TRUE);
		boolean encontrado = false;
		
		// se debe chequear si el comible ya existe en la comidadDieta para sumar la cantidad de ingeridos,
		// en caso de no existir se agrega
		Iterator<ComidaDieta> iterator = dieta.getComidasDieta().iterator();
		while (iterator.hasNext()) {
			ComidaDieta comidaDieta = (ComidaDieta) iterator.next();
			if (TipoComida.valueOf(comida).equals(comidaDieta.getTipo())) {
				
				Ingerido ingeridoPrevio = Ingerido.findByComidaDieta(comidaDieta.getId(), alimentoId);
				if (ingeridoPrevio != null) {
					// sumar cantidad porque ya existe
					ingeridoPrevio.setCantPorcionesIngeridas(ingeridoPrevio.getCantPorcionesIngeridas() + cantPorciones);
					ingeridoPrevio.save();
				} else {
					comidaDieta.agregarIngerido(ingerido);
				}
				encontrado = true;
				break;
			}
		}
		
		if (!encontrado) {
			ComidaDieta comidaDieta = new ComidaDieta();
			comidaDieta.setTipo(TipoComida.valueOf(comida));
			comidaDieta.agregarIngerido(ingerido);
			dieta.getComidasDieta().add(comidaDieta);
		}
		
		//registrar como frecuente
		Paciente paciente = (Paciente)getUsuarioLogueado();
		Frecuente findIfExists = Frecuente.findIfExists(paciente.getId(), comible.getId());
		
		if (findIfExists != null) {
			// sumar cantidad
			findIfExists.setCantidad(findIfExists.getCantidad() + cantPorciones);
			findIfExists.save();
		} else {
			Frecuente frecuente = new Frecuente(ingerido.getComible(), cantPorciones, paciente);
			paciente.getFrecuentes().add(frecuente);
			paciente.save();
		}
		
		dieta.save();
		
		return dieta.calcularCaloriasConsumidas();
		
	}
	
	/**
	 * Elimina el alimento ingerido segun el tipo de comida
	 */
	public static Integer eliminarAlimento(Long dietaId, String comida, Long alimentoId) throws Exception {
//		System.out.println("dietaId: "+ dietaId + " comida: "+ comida + " alimentoId: "+ alimentoId);
		Dieta dieta = Dieta.findById(dietaId);
		
		Iterator<ComidaDieta> iterator = dieta.getComidasDieta().iterator();
		while (iterator.hasNext()) {
			ComidaDieta comidaDieta = (ComidaDieta) iterator.next();
			if (TipoComida.valueOf(comida).equals(comidaDieta.getTipo())) {
				if (comidaDieta.getIngeridos().remove(Ingerido.findByComidaDieta(comidaDieta.getId(), alimentoId))) {
					break;
				}
			}
		}
		
		dieta.save();
		return dieta.calcularCaloriasConsumidas();
	}
	
	/**
	 * Modifica la cantidad de porciones de un ingerido 
	 */
	public static Integer modificarIngerido(Long dietaId, String comida, Long comibleId, Integer cantPorciones) throws Exception {
		Dieta dieta = Dieta.findById(dietaId);
		Iterator<ComidaDieta> iterator = dieta.getComidasDieta().iterator();
		
		while (iterator.hasNext()) {
			ComidaDieta comidaDieta = (ComidaDieta) iterator.next();
			if (TipoComida.valueOf(comida).equals(comidaDieta.getTipo())) {
				Ingerido ingerido = Ingerido.findByComidaDieta(comidaDieta.getId(), comibleId);
				ingerido.setCantPorcionesIngeridas(cantPorciones);
				ingerido.setConsumido(Boolean.TRUE);
				ingerido.save();
				break;
			}
		}
		dieta.save();
		return dieta.calcularCaloriasConsumidas();
	}
	
	/**
	 * Retorna los ids correspondientes a cada dieta segun el dia de la semana
	 */
	private static Long[] getIdsSemanaDieta(Long planId) {
		
		Date hoy = new Date();
		Calendar calendar = Calendar.getInstance(new Locale("es"));
		
		calendar.clear();
		calendar.setTime(hoy);
		Long[] ids = new Long[7];
		
		Dieta dieta;
		for (int i = 0; i < 7; i++) {
			if (i == 0) {
				calendar.add(Calendar.DAY_OF_YEAR, -(calendar.get(Calendar.DAY_OF_WEEK)-1));
			}
			dieta = Dieta.findByFecha(planId, calendar.getTime());
			ids[i] = dieta == null ? 0 : dieta.getId();
			//TODO: nico... revisar casos particular de dias semana y meses
//			calendar.add(Calendar.DAY_OF_MONTH, 1);
			calendar.add(Calendar.DAY_OF_YEAR, 1);
		}
		
		return ids;
	}
}
